package com.dupf.upms.server.controller.manage;

import com.baidu.unbiz.fluentvalidator.ComplexResult;
import com.baidu.unbiz.fluentvalidator.FluentValidator;
import com.baidu.unbiz.fluentvalidator.ResultCollectors;
import com.dupf.common.base.BaseController;
import com.dupf.common.util.ItvJsonUtil;
import com.dupf.common.util.MD5Util;
import com.dupf.common.util.RedisUtil;
import com.dupf.common.validator.LengthValidator;
import com.dupf.common.validator.NotNullValidator;
import com.dupf.upms.common.constant.UpmsResult;
import com.dupf.upms.common.constant.UpmsResultConstant;
import com.dupf.upms.dao.model.*;
import com.dupf.upms.rpc.api.*;
import com.dupf.upms.dao.model.UpmsRole;
import com.dupf.upms.dao.model.UpmsUser;
import com.dupf.upms.dao.model.UpmsUserExample;
import com.dupf.upms.dao.model.UpmsUserRole;
import com.dupf.upms.rpc.api.UpmsApiService;
import com.dupf.upms.rpc.api.UpmsUserOrganizationService;
import com.dupf.upms.rpc.api.UpmsUserRoleService;
import com.dupf.upms.rpc.api.UpmsUserService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.subject.Subject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 用户controller
 * Created by dupf on 2018/3/1.
 */
@Controller
@Api(value = "用户管理", description = "用户管理")
@RequestMapping("/employee")
public class UpmsEmployeeController extends BaseController {

    private static final Logger LOGGER = LoggerFactory.getLogger(UpmsEmployeeController.class);

    @Autowired
    private UpmsUserService upmsUserService;

    @Autowired
    private UpmsUserOrganizationService upmsUserOrganizationService;

    @Autowired
    private UpmsApiService upmsApiService;

    @Autowired
    private UpmsUserRoleService upmsUserRoleService;

    @Autowired
    private UpmsOrganizationService upmsOrganizationService;

    @ApiOperation(value = "用户列表")
    @RequestMapping(value = "/list", method = RequestMethod.GET)
    @ResponseBody
    public Object list(
            @RequestParam(required = false, defaultValue = "0", value = "offset") int offset,
            @RequestParam(required = false, defaultValue = "20", value = "limit") int limit,
            HttpServletRequest request) {
        Integer orgId = (Integer) request.getAttribute("currentOrgId");

        List<Integer> userIds = upmsUserOrganizationService.getUserIdsByOrgId(orgId);

        UpmsUserExample upmsUserExample = new UpmsUserExample();
        upmsUserExample.createCriteria().andUserIdIn(userIds);
        List<UpmsUser> rows = upmsUserService.selectByExampleForOffsetPage(upmsUserExample, offset, limit);
        long total = userIds.size();
        Map<String, Object> result = new HashMap<>();
        result.put("list", rows);
        result.put("total", total);
        return new UpmsResult(UpmsResultConstant.SUCCESS, result);
    }

    @ApiOperation(value = "新增用户")
    @RequiresRoles(value = {"admin", "operator", "corpAdmin", "secondAccount"}, logical = Logical.OR)
    @RequestMapping(value = "/create", method = RequestMethod.POST)
    @ResponseBody
    public Object create(HttpServletRequest request) throws IOException {
        Integer orgId = (Integer) request.getAttribute("currentOrgId");

        String requestStr = super.getInputStream(request);
        JSONObject data = JSONObject.fromObject(requestStr);
        Integer roleId = data.getInt("roleId");
        data.remove("roleId");

        UpmsOrganization organization = upmsOrganizationService.selectByPrimaryKey(orgId);
        if(organization == null){
            return new UpmsResult(UpmsResultConstant.NOT_EXISTED_ORG, "企业不存在！");
        }

        UpmsUserOrganizationExample userOrganizationExample = new UpmsUserOrganizationExample();
        userOrganizationExample.createCriteria().andOrganizationIdEqualTo(orgId);
//        long orgUserCount = upmsUserOrganizationService.countByExample(userOrganizationExample);
        List<UpmsUserOrganization> userOrganizations = upmsUserOrganizationService.selectByExample(userOrganizationExample);

        if(!CollectionUtils.isEmpty(userOrganizations)) {
            UpmsUserRoleExample userRoleExample = new UpmsUserRoleExample();
            // 排除运营人员
            userRoleExample.createCriteria().andUserIdIn(userOrganizations.stream().map(UpmsUserOrganization::getUserId).collect(Collectors.toList())).andRoleIdGreaterThanOrEqualTo(3);
            long orgUserCount = upmsUserRoleService.countByExample(userRoleExample);

            if (orgUserCount >= organization.getTotalCount()) {
                return new UpmsResult(UpmsResultConstant.OVER_LIMIT_COUNT, "超出账号数量限制，请联系管理员！");
            }
        }

        UpmsUser upmsUser = ItvJsonUtil.readValue(data.toString(), UpmsUser.class);

        ComplexResult result = FluentValidator.checkAll()
                .on(upmsUser.getUsername(), new LengthValidator(5, 20, "帐号"))
                .on(upmsUser.getPassword(), new LengthValidator(5, 32, "密码"))
                .on(upmsUser.getRealname(), new NotNullValidator("姓名"))
                .doValidate()
                .result(ResultCollectors.toComplex());
        if (!result.isSuccess()) {
            return new UpmsResult(UpmsResultConstant.INVALID_LENGTH, result.getErrors());
        }

        UpmsUserExample example = new UpmsUserExample();
        example.createCriteria().andUsernameEqualTo(upmsUser.getUsername());
        int count = upmsUserService.countByExample(example);
        if (count > 0) {
            return new UpmsResult(UpmsResultConstant.EXISTED_USERNAME, "帐号名已存在！");
        }

        Integer userId = upmsApiService.createEmployee(upmsUser, orgId, roleId);
        if (userId == null) {
            return new UpmsResult(UpmsResultConstant.FAILED, "添加账号失败！");
        }

        return new UpmsResult(UpmsResultConstant.SUCCESS, upmsUser.getUserId());
    }

    @ApiOperation(value = "修改用户")
    @RequiresRoles(value = {"admin", "operator", "corpAdmin", "secondAccount"}, logical = Logical.OR)
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ResponseBody
    public Object update(HttpServletRequest request) throws IOException {
        Integer orgId = (Integer) request.getAttribute("currentOrgId");

        String requestStr = super.getInputStream(request);
        JSONObject data = JSONObject.fromObject(requestStr);
        Integer roleId = data.optInt("roleId", 0);
        data.remove("roleId");

        UpmsUser upmsUser = ItvJsonUtil.readValue(data.toString(), UpmsUser.class);

        if (!StringUtils.isEmpty(upmsUser.getUsername())) {
            UpmsUserExample example = new UpmsUserExample();
            example.createCriteria().andUsernameEqualTo(upmsUser.getUsername());
            int count = upmsUserService.countByExample(example);
            if (count > 0) {
                return new UpmsResult(UpmsResultConstant.EXISTED_USERNAME, "帐号已存在！");
            }
        }

        long time = System.currentTimeMillis();
        if (upmsUser.getPassword() != null) {
            String salt = UUID.randomUUID().toString().replaceAll("-", "");
            upmsUser.setSalt(salt);
            upmsUser.setPassword(MD5Util.md5(upmsUser.getPassword() + upmsUser.getSalt()));
        }
        upmsUser.setUtime(time);
        int updateCount = upmsUserService.updateByPrimaryKeySelective(upmsUser);

        if (roleId != 0 && updateCount > 0) {
            UpmsUserRole upmsUserRole = new UpmsUserRole();
            upmsUserRole.setRoleId(roleId);
            upmsUserRole.setUserId(upmsUser.getUserId());

            UpmsUserRoleExample userRoleExample = new UpmsUserRoleExample();
            userRoleExample.createCriteria().andUserIdEqualTo(upmsUser.getUserId());
            upmsUserRoleService.updateByExampleSelective(upmsUserRole, userRoleExample);
        }

        try {
            UpmsUser upmsUser1 = upmsUserService.selectByPrimaryKey(upmsUser.getUserId());
            RedisUtil.remove("user:info:redis:prefix:" + upmsUser1.getUsername());
        } catch (Exception e){

        }
        return new UpmsResult(UpmsResultConstant.SUCCESS, updateCount);
    }

    @ApiOperation(value = "获取用户信息")
    @RequestMapping(value = "/info", method = RequestMethod.GET)
    @ResponseBody
    public Object info(HttpServletRequest request) {
        JSONObject data = JSONObject.fromObject(request.getAttribute("upmsUser"));
        return new UpmsResult(UpmsResultConstant.SUCCESS, data);
    }

    @ApiOperation(value = "修改个人信息")
    @RequestMapping(value = "/update/private", method = RequestMethod.POST)
    @ResponseBody
    public Object updateInfo(@RequestBody UpmsUser upmsUser, HttpServletRequest request) {
        Integer userId = (Integer) request.getAttribute("currentUserId");
        long time = System.currentTimeMillis();
        upmsUser.setUserId(userId);
        upmsUser.setUtime(time);

        if(!StringUtils.isEmpty(upmsUser.getPassword())) {
            String salt = UUID.randomUUID().toString().replaceAll("-", "");
            upmsUser.setSalt(salt);
            upmsUser.setPassword(MD5Util.md5(upmsUser.getPassword() + upmsUser.getSalt()));
        }
        upmsUser.setLocked(null);
        upmsUser.setCtime(null);
        int count = upmsUserService.updateByPrimaryKeySelective(upmsUser);

        try {
            Subject subject = SecurityUtils.getSubject();
            String username = (String) subject.getPrincipal();
            RedisUtil.remove("user:info:redis:prefix:" + username);
        } catch (Exception e){

        }
        return new UpmsResult(UpmsResultConstant.SUCCESS, count);
    }

    @ApiOperation(value = "可操作的用户列表")
    @RequiresRoles(value = {"admin", "operator", "corpAdmin", "secondAccount"}, logical = Logical.OR)
    @RequestMapping(value = "/operable-employee-names", method = RequestMethod.GET)
    @ResponseBody
    public Object operableEmployeeNameList(HttpServletRequest request) {
        Integer orgId = (Integer) request.getAttribute("currentOrgId");

        Subject subject = SecurityUtils.getSubject();
        String username = (String) subject.getPrincipal();

        JSONArray result = upmsApiService.getOperableListJson(username, orgId);

        return new UpmsResult(UpmsResultConstant.SUCCESS, result);
    }

    @ApiOperation(value = "可操作的用户列表")
    @RequiresRoles(value = {"admin", "operator", "corpAdmin", "secondAccount"}, logical = Logical.OR)
    @RequestMapping(value = "/operable-employee", method = RequestMethod.GET)
    @ResponseBody
    public Object operableEmployeeList( HttpServletRequest request,
                                        @RequestParam(required = false, defaultValue = "0", value = "offset") int offset,
                                        @RequestParam(required = false, defaultValue = "20", value = "limit") int limit) {
        Integer orgId = (Integer) request.getAttribute("currentOrgId");

        Subject subject = SecurityUtils.getSubject();
        String username = (String) subject.getPrincipal();

        JSONObject result = upmsApiService.getOperableUserListWithRole(username, orgId, offset, limit);

        return new UpmsResult(UpmsResultConstant.SUCCESS, result);
    }

    @ApiOperation(value = "可操作的角色列表")
    @RequiresRoles(value = {"admin", "operator", "corpAdmin", "secondAccount"}, logical = Logical.OR)
    @RequestMapping(value = "/operable-roles", method = RequestMethod.GET)
    @ResponseBody
    public Object operableRoleList(HttpServletRequest request) {
        Integer orgId = (Integer) request.getAttribute("currentOrgId");

        Subject subject = SecurityUtils.getSubject();
        String username = (String) subject.getPrincipal();

        UpmsUser upmsUser = upmsApiService.selectUpmsUserByUsername(username);

        List<UpmsRole> result = upmsApiService.getOperableRoles(upmsUser.getUserId());
        return new UpmsResult(UpmsResultConstant.SUCCESS, result);
    }
}